package com.zly.bscloud.service.impl;

import com.zly.bscloud.dto.UserDTO;
//import com.zly.bscloud.entity.LoginUser;
import com.zly.bscloud.entity.User;
import com.zly.bscloud.mapper.UserMapper;
import com.zly.bscloud.service.UserService;
import com.zly.bscloud.utils.entity.StatusCode;
import com.zly.bscloud.utils.exception.BpException;
import com.zly.bscloud.utils.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.security.authentication.AuthenticationManager;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.Authentication;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 用户service层实现类
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisCache redisCache;
//    @Autowired
//    private AuthenticationManager authenticationManager;
//    @Autowired
//    private RedisCache redisCache;

    /**
     * 用户登录/注册方法
     * @param user 用户信息,里面有用户的手机号和密码
     * @return 返回不包含敏感信息的dto对象
     */
    @Transactional
    public UserDTO userLogin(User user) {
        if(!RegExpUtils.username(user.getUsername())){
            throw new BpException(StatusCode.InvalidUsername);
        }
        if (!RegExpUtils.password(user.getPassword()))
            throw new BpException(StatusCode.InvalidPassword);

//        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
//        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//        if(Objects.isNull(authenticate)){
//            throw new BpException(StatusCode.InvalidUserReset);
//        }
//        //使用userid生成token
//        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
//        String userId = loginUser.getUser().getId().toString();
//        String jwt = JWTUtils.createJWT(userId);
//        //authenticate存入redis
//        redisCache.setCacheObject("login:"+userId,loginUser);
        //把token响应给前端
//        HashMap<String,String> map = new HashMap<>();
//        map.put("token",jwt);
//        return ResultGenerator.genSuccessResult(200,map,"登陆成功");
        UserDTO userDTO;
        //先查看是否有这个用户名,若是没有这个用户名,则进行注册,若是有这个手机号,则进行密码加密再次校验
        User dbSelectUser = new User();
        dbSelectUser.setUsername(user.getUsername());
        int userCount = userMapper.selectCount(dbSelectUser);
        System.out.println(userCount);
        System.out.println(user.toString());
        //对密码进行加密
        user.setPassword(MD5Utils.MD5Salt(user.getPassword(),user.getUsername()));
        //若是查询到的数据不为1 , 则用户没有注册 , 给用户进行注册
        if (userCount != 1){
            //id为uuid随机生成
            user.setId(UUIDUtils.UUID());
            //头像为默认头像

            LocalDateTime dateTime = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            user.setRegtime(dateTime.format(formatter));
            user.setType("普通用户");
            //插入进数据库
            int count = userMapper.insert(user);
            //只要不为1 则操作失败 抛出异常
            if (count != 1)
                throw new BpException(StatusCode.UserRegisterFailure);


            //转换成dto对象返回给前端
            userDTO = BeanHelper.copyProperties(user, UserDTO.class);
        } else {
            // 若是为1 则表明用户已经注册过 就进行密码校验
//        System.out.println(user.toString());
//        List<User> users=userMapper.selectAll();
//        System.out.println(users.toString());
//        int count=userMapper.selectCount(user);
//        User verifyPassword = userMapper.selectOne(user);
//        System.out.println(count);
            //若是这次校验密码为空 , 则抛出异常 , 说明其密码错误
            dbSelectUser = userMapper.selectOne(dbSelectUser);
            System.out.println(dbSelectUser);
            System.out.println(user.getPassword());
            System.out.println(dbSelectUser.getPassword());
            if (!user.getPassword().equals(dbSelectUser.getPassword()))
                throw new BpException(StatusCode.InvalidUserReset);
            user = dbSelectUser;
            //若是没有没有抛出异常 , 则向前端返回dto对象
            userDTO = BeanHelper.copyProperties(dbSelectUser, UserDTO.class);
        }

        System.out.println("useruser");
        //redis存user信息
        Map<String, String> map = new HashMap<>();
        map.put("id", user.getId());
        map.put("username", user.getUsername());
        map.put("password", user.getPassword());
        map.put("nickname", user.getNickname());
        map.put("telephone", user.getTelephone());
        map.put("headphoto", user.getHeadphoto());
        map.put("regtime", user.getRegtime());
        map.put("sex", user.getSex().toString());
        map.put("location", user.getLocation());
        map.put("type", user.getType());
        System.out.println("user:"+user.getId());
        System.out.println(map);
        redisCache.setCacheMap("user:"+user.getId(), map);
//        redisCache.deleteObject("user:"+user.getId());
        System.out.println(redisCache.getCacheMap("user:"+user.getId()));


        return userDTO;
    }

    /**
     * 重新设置用户密码
     * @param map map其中包含用户名 , 新密码 , 和旧密码
     */
    @Transactional
    public void userReset(Map<String,String> map) {
        System.out.println(map);

        if (!RegExpUtils.password(map.get("upassword")) || !RegExpUtils.password(map.get("password")))
            throw new BpException(StatusCode.InvalidPassword);
        //首先查出是不是有这个用户名和这个老密码
        User dbSelectUser = new User();
        dbSelectUser.setUsername(map.get("username"));
        dbSelectUser.setPassword(MD5Utils.MD5Salt(map.get("upassword"),map.get("username")));
        User selectOne = userMapper.selectOne(dbSelectUser);
        // 通过用户名和旧密码查出这个用户若是为空
        // 则证明密码或者用户名输入错误 , 抛出异常
        if (selectOne == null)
            throw new BpException(StatusCode.InvalidUserReset);
        //若是不为空 则更新新密码
        selectOne.setPassword(MD5Utils.MD5Salt(map.get("password"),map.get("username")));
        int count = userMapper.updateByPrimaryKey(selectOne);
        // 不为1 则更新失败 抛出异常
        if (count != 1)
            throw new BpException(StatusCode.InvalidUserReset);
    }

    /**
     * 重设用户昵称
     * @param map 其中包括用户id和新昵称
     * @return 返回不包含用户敏感信息的dto对象
     */
    @Transactional
    public UserDTO resetNickname(Map<String, String> map) {
        System.out.println(map);
        //先检验昵称 , 若是昵称不正确 , 则抛出异常
        //if (!RegExpUtils.username(map.get("nickname")))
        //    throw new BpException(StatusCode.InvalidUsername);
        User user = new User();
        user.setId(map.get("id"));
        // 首先查出此用户
        User selectOne = userMapper.selectOne(user);
        selectOne.setNickname(map.get("nickname"));
        //再次进行更新
        int count = userMapper.updateByPrimaryKey(selectOne);
        // 如果不为1 则抛出异常
        if (count != 1)
            throw new BpException(StatusCode.InvalidNicknameReset);
        //转换成dto对象返回给前端
        UserDTO userDTO = BeanHelper.copyProperties(selectOne, UserDTO.class);
        return userDTO;
    }

    /**
     * 重设用户手机号
     * @param map 其中包括用户id和手机号
     * @return 返回不包含用户敏感信息的dto对象
     */
    @Transactional
    public UserDTO resetTelephone(Map<String, String> map) {
        System.out.println(map);
        //先检验手机号 , 若是手机号不正确 , 则抛出异常
        if (!RegExpUtils.telephone(map.get("telephone")))
            throw new BpException(StatusCode.InvalidPhone);
        User user = new User();
        user.setId(map.get("id"));
        // 首先查出此用户
        User selectOne = userMapper.selectOne(user);
        selectOne.setTelephone(map.get("telephone"));
        //再次进行更新
        int count = userMapper.updateByPrimaryKey(selectOne);
        // 如果不为1 则抛出异常
        if (count != 1)
            throw new BpException(StatusCode.InvalidTelephoneReset);
        //转换成dto对象返回给前端
        UserDTO userDTO = BeanHelper.copyProperties(selectOne, UserDTO.class);
        return userDTO;
    }

    /**
     * 重设用户地址
     * @param map 其中包括用户id和新地址
     * @return 返回不包含用户敏感信息的dto对象
     */
    @Transactional
    public UserDTO resetLocation(Map<String, String> map) {
        System.out.println(map);

        User user = new User();
        user.setId(map.get("id"));
        // 首先查出此用户
        User selectOne = userMapper.selectOne(user);
        selectOne.setLocation(map.get("location"));
        //再次进行更新
        int count = userMapper.updateByPrimaryKey(selectOne);
        // 如果不为1 则抛出异常
        if (count != 1)
            throw new BpException(StatusCode.InvalidLocationReset);
        //转换成dto对象返回给前端
        UserDTO userDTO = BeanHelper.copyProperties(selectOne, UserDTO.class);
        return userDTO;
    }

    /**
     * 重设用户性别
     * @param map 其中包括用户id和新性别
     * @return 返回不包含用户敏感信息的dto对象
     */
    @Transactional
    public UserDTO resetSex(Map<String, String> map) {
        System.out.println(map);

        User user = new User();
        user.setId(map.get("id"));
        // 首先查出此用户
        User selectOne = userMapper.selectOne(user);
        System.out.println(selectOne+"111");
        selectOne.setSex(Integer.parseInt(map.get("index"))+1);
        //再次进行更新
        int count = userMapper.updateByPrimaryKey(selectOne);
        System.out.println(count);
        // 如果不为1 则抛出异常
        if (count != 1)
            throw new BpException(StatusCode.InvalidSexReset);
        //转换成dto对象返回给前端
        UserDTO userDTO = BeanHelper.copyProperties(selectOne, UserDTO.class);
        return userDTO;
    }

    /**
     * 获得全部用户的dto信息
     * @return 返回所有用户的dto信息
     */
    @Override
    public List<UserDTO> getAllUser() {
        List<User> userList = userMapper.selectAll();
        List<UserDTO> userDTOList = BeanHelper.copyWithCollection(userList, UserDTO.class);
        return userDTOList;
    }

    /**
     * 通过用户名查找对应的用户信息
     * @param username 查找的用户名
     * @return 对应的用户集合
     */
    @Override
    public List<UserDTO> getUserByUsername(String username) {
        if (username.equals("null"))
            username = "";
        Example example = new Example(User.class);
        example.createCriteria().andLike("username","%" + username + "%");
        List<User> userList = userMapper.selectByExample(example);
        // 转换成dto集合
        List<UserDTO> userDTOList = BeanHelper.copyWithCollection(userList, UserDTO.class);
        return userDTOList;
    }

    /**
     * 通过用户id精确查找用户信息
     * @param uId 用户id
     * @return 返回对应的用户信息
     */
    @Override
    public UserDTO getUserByUId(String uId) {
        User user = userMapper.selectByPrimaryKey(uId);
        UserDTO userDTO = BeanHelper.copyProperties(user, UserDTO.class);
        return userDTO;
    }

    @Override
    public List<UserDTO> findAllUsers() {

        // 创建Example
        Example example = new Example(User.class);
        // 创建Criteria
        //Example.Criteria criteria = example.createCriteria();
        // 添加条件
        //criteria.andEqualTo("received", 0);
        example.setOrderByClause("regtime desc");
        List<User> userList = userMapper.selectByExample(example);

        List<UserDTO> userDTOList = BeanHelper.copyWithCollection(userList, UserDTO.class);
        return userDTOList;
    }
}
